import os
import uuid
from datetime import datetime, timedelta
from io import BytesIO
from typing import Optional, Dict, Any

from minio import Minio
from minio.error import S3Error
from loguru import logger

from ai_platform.config.settings import settings


class MinIOService:
    """MinIO对象存储服务"""

    def __init__(self):
        """初始化MinIO客户端"""
        self.client = Minio(
            endpoint=settings.minio_endpoint,
            access_key=settings.minio_access_key,
            secret_key=settings.minio_secret_key,
            secure=settings.minio_secure
        )

    async def upload_file(
        self,
        knowledge_base_id: str,
        bucket_name: str,
        file_data: bytes,
        original_filename: str,
        content_type: str = "application/octet-stream"
    ) -> Dict[str, Any]:
        """
        上传文件到MinIO
        """
        try:
            # 生成唯一文件名
            file_id = str(uuid.uuid4())
            file_extension = os.path.splitext(original_filename)[1]
            object_name = f"{datetime.now().strftime('%Y/%m/%d')}/{file_id}{file_extension}"

            file_stream = BytesIO(file_data)

            self.client.put_object(
                bucket_name=bucket_name,
                object_name=object_name,
                data=file_stream,
                length=len(file_data),
                content_type=content_type
            )

            # 生成下载URL
            download_url = self.get_download_url(bucket_name, object_name)

            upload_info = {
                "file_id": file_id,
                "original_filename": original_filename,
                "object_name": object_name,
                "bucket_name": bucket_name,
                "download_url": download_url,
                "file_size": len(file_data),
                "content_type": content_type,
                "knowledge_base_id": knowledge_base_id,
                "upload_time": datetime.now().isoformat(),
            }

            logger.info(f"文件上传成功: {original_filename} -> {object_name}")
            return upload_info

        except S3Error as e:
            logger.exception(f"文件上传失败: {e}")
            raise

    def get_download_url(self, bucket_name: str, object_name: str, expires: int = 3600) -> str:
        """
        获取文件下载URL

        """
        try:
            return self.client.presigned_get_object(
                bucket_name=bucket_name,
                object_name=object_name,
                expires=timedelta(seconds=expires)
            )
        except S3Error as e:
            logger.exception(f"生成下载URL失败: {e}")
            raise

    async def delete_file(self, bucket_name: str, object_name: str) -> bool:
        """
        删除文件
        """
        try:
            self.client.remove_object(
                bucket_name=bucket_name,
                object_name=object_name
            )
            logger.info(f"文件删除成功: {object_name}")
            return True
        except S3Error as e:
            logger.exception(f"文件删除失败: {e}")
            return False

    async def get_file_info(self, bucket_name: str, object_name: str) -> Optional[Dict[str, Any]]:
        """
        获取文件信息
        """
        try:
            stat = self.client.stat_object(
                bucket_name=bucket_name,
                object_name=object_name
            )
            return {
                "object_name": object_name,
                "size": stat.size,
                "last_modified": stat.last_modified.isoformat(),
                "content_type": stat.content_type,
                "etag": stat.etag
            }
        except S3Error as e:
            logger.exception(f"获取文件信息失败: {e}")
            return None

    async def list_files(self, bucket_name: str, prefix: str = "", limit: int = 100) -> list:
        """
        列出文件
        """
        try:
            objects = self.client.list_objects(
                bucket_name=bucket_name,
                prefix=prefix,
                recursive=True
            )

            files = []
            count = 0
            for obj in objects:
                if count >= limit:
                    break
                files.append({
                    "object_name": obj.object_name,
                    "size": obj.size,
                    "last_modified": obj.last_modified.isoformat(),
                    "etag": obj.etag
                })
                count += 1

            return files
        except S3Error as e:
            logger.exception(f"列出文件失败: {e}")
            return []

    async def read_file(self, bucket_name: str, object_name: str) -> Optional[bytes]:
        """
        读取文件内容
        """
        try:
            response = self.client.get_object(
                bucket_name=bucket_name,
                object_name=object_name
            )
            # 读取所有数据
            file_data = response.read()
            response.close()
            response.release_conn()

            logger.info(f"文件读取成功: {object_name}")
            return file_data

        except S3Error as e:
            logger.exception(f"文件读取失败: {e}")
            return None
